package com.wqnmdb.im.service.impl;

import com.mongodb.client.result.UpdateResult;
import com.wqnmdb.im.domain.mongo.ImMessage;
import com.wqnmdb.im.domain.mongo.ImSession;
import com.wqnmdb.im.domain.mongo.ImUser;
import com.wqnmdb.im.domain.resp.R;
import com.wqnmdb.im.domain.resp.RespUtils;
import com.wqnmdb.im.netty.dispose.impl.AsynAndCacheService;
import com.wqnmdb.im.service.MsgService;
import com.wqnmdb.im.service.mongo.MongoPage;
import com.wqnmdb.im.service.mongo.MongoService;
import com.wqnmdb.im.service.redis.RedisStringService;
import com.wqnmdb.im.utils.DateUtil;
import com.wqnmdb.im.utils.PBEUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;


/**
 * 消息服务
 */
@Slf4j
@Service
public class MsgServiceImpl implements MsgService {

    @Autowired
    private MongoService mongoService;

    @Autowired
    private RedisStringService redisStringService;

    @Autowired
    private AsynAndCacheService asynAndCacheService;


    /**
     * 获取会话列表
     */
    @Override
    public ResponseEntity<R> getList(String accessKey, String secretKey, String appName, Integer pageNum, Integer pageSize) {
        ImUser user = checkUser(accessKey, secretKey, appName);
        if (user == null) {
            return RespUtils.fail("检查未通过");
        }

        //查询会话
        MongoPage page = new MongoPage(pageSize);
        page.setPageNo(pageNum);
        Criteria criteria = new Criteria();
        criteria.orOperator(
                Criteria.where("originUserId").is(user.getUserId()).and("originUserDel").is(0).and("type").is(1).and("status").is(1),
                Criteria.where("particUserId").is(user.getUserId()).and("particUserDel").is(0).and("type").is(1).and("status").is(1));
        MongoPage sessionPage = mongoService.findPage(page, new Query(criteria), ImSession.class, asynAndCacheService.getSessionCollectionName(appName));
        return RespUtils.success(sessionPage);
    }

    /**
     * 通过sessionId获取消息
     */
    @Override
    public ResponseEntity<R> getListBySessionId(String sessionId, String accessKey, String secretKey, String appName, Integer pageNum, Integer pageSize) {
        ImUser user = checkUser(accessKey, secretKey, appName);
        if (user == null) {
            return RespUtils.fail("检查未通过");
        }
        ImSession session = mongoService.findOne(new Query(Criteria.where("id").is(sessionId).and("status").is(1)),
                ImSession.class, asynAndCacheService.getSessionCollectionName(appName));
        if (session == null) {
            return RespUtils.fail("会话不存在");
        }
        Criteria criteria = new Criteria();
        if (session.getOriginUserId().equals(user.getUserId())) {
            criteria.and("oDel").is(0);
        } else if (session.getParticUserId().equals(user.getUserId())) {
            criteria.and("pDel").is(0);
        } else {
            return RespUtils.fail("这不是你的会话消息哦~");
        }
        criteria.and("sessionId").is(sessionId);
        criteria.and("status").in(Arrays.asList(-1, 1, 2));
        //查询消息
        MongoPage page = new MongoPage(pageSize);
        page.setPageNo(pageNum);
        MongoPage msgPage = mongoService.findPage(page, new Query(criteria), ImMessage.class, asynAndCacheService.getMsgCollectionName(appName));

        if (msgPage.getResult() != null) {
            List<ImMessage> msgs = (List<ImMessage>) msgPage.getResult();
            msgs.forEach(msg -> {
                if (msg.getStatus() == -1) {
                    msg.setMsgData("");
                }
            });
        }
        return RespUtils.success(msgPage);
    }

    /**
     * 删除会话
     */
    @Override
    public ResponseEntity<R> delSessionById(String sessionId, String accessKey, String secretKey, String appName) {
        ImUser user = checkUser(accessKey, secretKey, appName);
        if (user != null) {
            //查询会话
            ImSession session = mongoService.findOne(new Query(Criteria.where("id").is(sessionId).and("status").is(1)),
                    ImSession.class, asynAndCacheService.getSessionCollectionName(appName));
            if (session != null) {
                Update updateSession = new Update();
                Update updateMsg = new Update();
                if (session.getOriginUserId().equals(user.getUserId()) && session.getParticUserId().equals(user.getUserId())) {
                    updateSession.set("originUserDel", 1);
                    updateSession.set("particUserDel", 1);
                    updateSession.set("status", 0);
                    updateMsg.set("pDel", 1);
                    updateMsg.set("oDel", 1);
                } else if (session.getOriginUserId().equals(user.getUserId())) {
                    updateSession.set("originUserDel", 1);
                    if (session.getParticUserDel() == 1) {
                        updateSession.set("status", 0);
                    }
                    updateMsg.set("oDel", 1);
                } else if (session.getParticUserId().equals(user.getUserId())) {
                    updateSession.set("particUserDel", 1);
                    if (session.getOriginUserDel() == 1) {
                        updateSession.set("status", 0);
                    }
                    updateMsg.set("pDel", 1);
                } else {
                    return RespUtils.fail("这不是你的会话消息哦~");
                }
                updateSession.set("updateTime", DateUtil.getNowInt());
                updateMsg.set("updateTime", DateUtil.getNowInt());
                UpdateResult updateS = mongoService.updateFirst(new Query(Criteria.where("id").is(sessionId)),
                        updateSession, ImSession.class, asynAndCacheService.getSessionCollectionName(appName));
                if (updateS.getModifiedCount() > 0) {
                    asynAndCacheService.delSessionCache(session, appName);
                    UpdateResult updateM = mongoService.updateMulti(new Query(Criteria.where("sessionId").is(sessionId)),
                            updateMsg, ImMessage.class, asynAndCacheService.getMsgCollectionName(appName));
                    log.info("删除消息数量：{}.", updateM.getModifiedCount());
                    return RespUtils.successMsg("成功");
                }
                return RespUtils.fail("失败");
            } else {
                return RespUtils.fail("会话不存在");
            }
        } else {
            return RespUtils.fail("检查未通过");
        }
    }

    @Override
    public ResponseEntity<R> getUserList() {
        //验证并保存用户
        String collectionName = asynAndCacheService.getUserCollectionName("xiangkan");
        List<ImUser> users = mongoService.find(
                new Query(Criteria.where("status").is(1)), ImUser.class, collectionName);
        return RespUtils.success(users);
    }

    /**
     * 校验用户
     */
    private ImUser checkUser(String accessKey, String secretKey, String appName) {
        ImUser user = mongoService.findOne(new Query(Criteria.where("auth").is(accessKey)
                .and("salt").is(secretKey).and("status").is(1)), ImUser.class, asynAndCacheService.getUserCollectionName(appName));
        if (user != null) {
            //校验
            String userId = PBEUtil.encryptAndDecrypt(accessKey, user.getPassword(), secretKey, 2);
            if (user.getUserId().equals(Integer.parseInt(userId))) {
                return user;
            }
        }
        return null;
    }
}

